/**
 * utils/symmetric.js
 *
 * 基于 Web Crypto (SubtleCrypto) 的 AES-GCM 对称加密工具
 * - 生成 256-bit AES 密钥（返回 Base64 编码）
 * - 导出 / 导入 Base64 编码的密钥
 * - encrypt(plain, base64Key) -> 返回 Base64( iv || cipher )
 * - decrypt(base64CipherWithIv, base64Key) -> 返回明文字符串
 *
 * 说明：
 *  - 使用 AES-GCM，iv 长度 12 bytes（96 bits），这是推荐值
 *  - 密文格式：把 iv（12 bytes）放在最前面，然后拼接 ciphertext，最后整体 base64 编码
 *  - 需要运行在支持 Web Crypto 的浏览器环境
 */

const SymmetricUtil = (function () {
  const algo = { name: "AES-GCM", length: 256 };
  const ivLength = 12; // bytes (96 bits) 推荐用于 GCM

  // ====== base64 编解码 helpers ======
  function bufToBase64(buffer) {
    const bytes = new Uint8Array(buffer);
    let binary = "";
    for (let i = 0; i < bytes.byteLength; i++) {
      binary += String.fromCharCode(bytes[i]);
    }
    return btoa(binary);
  }

  function base64ToBuf(base64) {
    const binary = atob(base64);
    const len = binary.length;
    const bytes = new Uint8Array(len);
    for (let i = 0; i < len; i++) {
      bytes[i] = binary.charCodeAt(i);
    }
    return bytes.buffer;
  }

  // ====== key 导入/导出 ======
  async function generateKeyBase64() {
    // 生成 CryptoKey 并导出为 base64
    const key = await window.crypto.subtle.generateKey(algo, true, ["encrypt", "decrypt"]);
    const raw = await window.crypto.subtle.exportKey("raw", key);
    return bufToBase64(raw);
  }

  async function importKeyFromBase64(base64Key) {
    const raw = base64ToBuf(base64Key);
    return await window.crypto.subtle.importKey("raw", raw, algo, true, ["encrypt", "decrypt"]);
  }

  async function exportKeyToBase64(cryptoKey) {
    const raw = await window.crypto.subtle.exportKey("raw", cryptoKey);
    return bufToBase64(raw);
  }

  // ====== AES-GCM 加密/解密 ======
  /**
   * 加密
   * @param {string} plainText - 明文字符串
   * @param {string} base64Key - Base64 编码的 AES 密钥
   * @returns {Promise<string>} Base64(iv + cipher)
   */
  async function encrypt(plainText, base64Key) {
    if (!plainText) return "";
    const key = await importKeyFromBase64(base64Key);
    const iv = window.crypto.getRandomValues(new Uint8Array(ivLength));
    const enc = new TextEncoder();
    const plainBuf = enc.encode(plainText);

    const cipherBuf = await window.crypto.subtle.encrypt(
      { name: "AES-GCM", iv: iv },
      key,
      plainBuf
    );

    // 拼接 iv + cipher
    const ivAndCipher = new Uint8Array(ivLength + cipherBuf.byteLength);
    ivAndCipher.set(iv, 0);
    ivAndCipher.set(new Uint8Array(cipherBuf), ivLength);
    return bufToBase64(ivAndCipher.buffer);
  }

  /**
   * 解密
   * @param {string} base64IvAndCipher - Base64(iv + cipher)
   * @param {string} base64Key - Base64 编码的 AES 密钥
   * @returns {Promise<string>} 明文字符串
   */
  async function decrypt(base64IvAndCipher, base64Key) {
    if (!base64IvAndCipher) return "";
    const key = await importKeyFromBase64(base64Key);
    const ivAndCipherBuf = base64ToBuf(base64IvAndCipher);
    const arr = new Uint8Array(ivAndCipherBuf);
    const iv = arr.slice(0, ivLength);
    const cipher = arr.slice(ivLength);
    const plainBuf = await window.crypto.subtle.decrypt(
      { name: "AES-GCM", iv: iv },
      key,
      cipher
    );
    const dec = new TextDecoder();
    return dec.decode(plainBuf);
  }

  // ====== 便捷：把 base64Key 保存到 localStorage（可选辅助） ======
  function saveKeyToLocalStorage(name, base64Key) {
    if (!name || !base64Key) return false;
    try {
      localStorage.setItem(name, base64Key);
      return true;
    } catch (e) {
      return false;
    }
  }

  function loadKeyFromLocalStorage(name) {
    return localStorage.getItem(name);
  }

  // ====== 导出 API ======
  return {
    generateKeyBase64,    // () => Promise<string>
    importKeyFromBase64,  // (base64Key) => Promise<CryptoKey>
    exportKeyToBase64,    // (CryptoKey) => Promise<string>
    encrypt,              // (plainText, base64Key) => Promise<string>  返回 Base64(iv+cipher)
    decrypt,              // (base64IvAndCipher, base64Key) => Promise<string>
    saveKeyToLocalStorage,
    loadKeyFromLocalStorage
  };
})();

export default SymmetricUtil;

/*
使用示例 (在 Vue 组件或其他模块中)：

import SymmetricUtil from '@/utils/symmetric';

// 生成密钥
const key = await SymmetricUtil.generateKeyBase64();
// key 是 Base64 字符串，可以传给后端或保存到 localStorage
SymmetricUtil.saveKeyToLocalStorage('my_aes_key', key);

// 加密
const cipherBase64 = await SymmetricUtil.encrypt('hello world', key);

// 解密
const plain = await SymmetricUtil.decrypt(cipherBase64, key);

注意：所有方法均为 Promise，请使用 await 或 then。
*/
